package simi;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.sshtools.j2ssh.SshClient;
import com.sshtools.j2ssh.session.SessionChannelClient;
import com.sshtools.j2ssh.connection.ChannelInputStream;
import com.sshtools.j2ssh.connection.ChannelOutputStream;

public class ChangePasswordServlet extends HttpServlet {

	/**
	 * Need a UID to extend HttpServlet
	 */
	private static final long serialVersionUID = 1L;
	private static long limitToChangePwd = SimiPropertyManager.getConfig().getLong("changePassword.timeLimit");

	public void doPost(HttpServletRequest req, HttpServletResponse res) {
		try {
			HttpSession theSession = req.getSession();
			boolean pwdChanged = changePassword(req, theSession);
			if (pwdChanged) {
				theSession.setAttribute(Constants.CP_MESSAGE,Constants.CP_SUCCESS);
				getServletConfig().getServletContext().getRequestDispatcher(Constants.CP_FORWARD).forward(req, res);
			} else {
				theSession.setAttribute(Constants.CP_ERROR,Constants.CP_FAILURE);
				getServletConfig().getServletContext().getRequestDispatcher(Constants.CP_ERROR_FORWARD).forward(req, res);
			}
		} catch (InterruptedException ie) {
			ie.printStackTrace();
		} catch (ServletException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private boolean changePassword(
		HttpServletRequest req,
		HttpSession theSession
	) throws IOException, InterruptedException {
		String oldpass = req.getParameter(Constants.CP_OLD_PWD_PARAM);
		String newpass = req.getParameter(Constants.CP_NEW_PWD_PARAM);
		String confirm = req.getParameter(Constants.CP_CON_PWD_PARAM);
		if(!confirm.equals(newpass))return false;
		String username = (String)theSession.getAttribute("username");
		String command = SimiPropertyManager.getConfig().getString("changePassword.command");
		String[] pFailure = SimiPropertyManager.getConfig().getStringArray("changePassword.failure");
		String[] pSuccess = SimiPropertyManager.getConfig().getStringArray("changePassword.success");
		String[] pUsername = SimiPropertyManager.getConfig().getStringArray("changePassword.username");
		String[] pOldpass = SimiPropertyManager.getConfig().getStringArray("changePassword.old");
		String[] pNewpass = SimiPropertyManager.getConfig().getStringArray("changePassword.new");
		SshClient ssh = (SshClient) theSession.getAttribute("connection");
		SessionChannelClient session = ssh.openSessionChannel();//not to be confused with "theSession"
		if(!(session.requestPseudoTerminal("ansi",80,24,0,0,""))) return false;
		if(!(session.startShell())) return false;
		ByteArrayOutputStream response = new ByteArrayOutputStream();
		boolean done = false;
		boolean good = false;
		boolean fail = false;
		session.getOutputStream().write((command + "\n").getBytes());
		while(!done){
			//System.out.println("----begin while loop -----");
			//System.out.println("----read char -----");
			int b = session.getInputStream().read();
			//System.out.print("----got char ");
			//System.out.print((int) b);
			//System.out.println(" -----");
			//System.out.print("----response size ");
			//System.out.print(response.size());
			//System.out.println(" ----");
			//System.out.println("----append response -----");
			response.write(b);
			//System.out.println("----show response -----");
			//System.out.println(response.toString());
			//System.out.println("----test fail -----");
			for(String p: pFailure) {
				//System.out.println(p);
				if (response.toString().matches("(?s)" + p)) {
					//System.out.println("---- match -----");
					fail = true;
					break;
				}
			}
			if(fail) break;
			//System.out.println("----test success -----");
			for(String p: pSuccess) {
				//System.out.println(p);
				if (response.toString().matches("(?s)" + p)) {
					//System.out.println("---- match -----");
					good = true;
					break;
				}
			}
			if(good) break;
			//System.out.println("----test username -----");
			for(String p: pUsername) {
				//System.out.println(p);
				if (response.toString().matches("(?s)" + p)) {
					//System.out.println("---- match -----");
					session.getOutputStream().write((username + "\n").getBytes());
					break;
				}
			}
			//System.out.println("----test oldpass -----");
			for(String p: pOldpass) {
				//System.out.println(p);
				if (response.toString().matches("(?s)" + p)) {
					//System.out.println("---- match -----");
					session.getOutputStream().write((oldpass + "\n").getBytes());
					break;
				}
			}
			//System.out.println("----test newpass -----");
			for(String p: pNewpass) {
				//System.out.println(p);
				if (response.toString().matches("(?s)" + p)) {
					//System.out.println("---- match -----");
					session.getOutputStream().write((newpass + "\n").getBytes());
					break;
				}
			}
			//System.out.println("----end while loop -----");	
		}
		session.close();
		System.out.println("-- changing password --");
		System.out.println(username);
		System.out.println(response.toString());
		return good;
	}
}
	/*
		//PasswordChanger pwdChanger = null;
		//OutputStream os = null;
		try {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			IOUtil iou = new IOUtil();
			iou.readWrite(session.getInputStream(), baos);
			os = session.getOutputStream();
			//String username = (String) theSession.getAttribute("username");
			//pwdChanger = new PasswordChanger(baos, os, username, oldPwd, newPwd);
			Thread theThread = new Thread(pwdChanger);
			theThread.start();

			theThread.join(limitToChangePwd);

			if (pwdChanger.isDone()) {
				return true;
			} else {
				// This will kill the thread if still running...
				pwdChanger.setExpired(true);
				return false;
			}

		} finally {
			if (pwdChanger != null)
				pwdChanger.setExpired(true);

			try {
				if (os != null)
					os.close();
			} catch (Exception e1) {
				e1.printStackTrace();
			}

			try {
				if (ssh != null)
					ssh.disconnect();
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
	}

}
*/